//
// Created by hujin on 2023/3/10.
//

#ifndef COSI_OPTIM_ENGINE_H
#define COSI_OPTIM_ENGINE_H

#include <queue>
#include <memory>
#include "global_stats.h"
#include "node_stats.h"
#include "functional"
template<typename T, typename I, typename EdgeData, typename NodeStat> class Optimizer;

template<typename T, typename I, typename EdgeData, typename NodeSt>
class Operation{
public:
    bool valid = true;
    T value;
    virtual void operate(Optimizer<T, I, EdgeData, NodeSt>&) = 0;

    bool operator<(const Operation &rhs) const {
        return valid < rhs.value || (valid == rhs.valid && &this < &rhs);
    }
};

template<typename T, typename I, typename EdgeData, typename NodeSt>
class Optimizer{
public:

    std::priority_queue<Operation<T, I, EdgeData, NodeSt>&> process_queue;

    virtual inline bool onOperate(Operation<T, I, EdgeData, NodeSt>&){
        return true;
    }

     virtual void perform_optimization(){
        while (!process_queue.empty()) {
            auto &x = process_queue.top();
            process_queue.pop();

            if(!onOperated(x)){
                break;
            }

            x.operate(*this);
        }
    }

    virtual void notify(Operation<T, I, EdgeData, NodeSt>& x) {
        process_queue.push(x);
    }

    virtual I request_new_id(){
        return new_id++;
    }



    explicit Optimizer(GlobalStats<EdgeData, I> graph, I num_vertices) : new_id(num_vertices), edge_map(graph) {}
//    virtual inline bool notify_changed();

// todo : initialize
protected:
    GlobalStats<EdgeData, I> edge_map;
    std::vector<NodeSt > node_stats;

    I new_id;
//    std::vector<I> parent_id;
//    std::vector<I> children_id;
};

#endif //COSI_OPTIM_ENGINE_H
